Microprocessors typically contain registers that are used in executing instructions. When the microprocessors execute instructions, data values are read from the registers and results of operations are written into the registers. For example, the ADD instruction, R1+R2=R3, adds the values held in registers R1 and R2 and puts the resulting sum into register R3. R1, R2, and R3 are identifiers associated with respective registers. The values being added together, R1 and R2, are referred to as source operands, while R3 is referred to as a destination register.
Traditional microprocessors sequentially execute instructions in a computer program, i.e., in the order that the instructions appear in the computer program. In the simplest case, an instruction is executed per a clock cycle. Many instructions may take more than one clock cycle to execute.
Superscalar processors, in contrast to traditional microprocessors, may issue and receive multiple instructions per clock cycle. With such processors, an instruction can be executed in a single clock cycle if there are no data dependencies, procedural dependencies, or resource conflicts that prevent execution of the instruction.
High performance processors, such as processors that adopt the UltraSPARC™ 5 architecture, use out-of-order processing, i.e., the processors process the instructions non-sequentially. Such high performance processors typically do not have a fixed relationship between a register identifier and the physical register referenced by the identifier. Thus, the identifier R1 may refer to a first physical register in one instruction and refer to a second physical register in another instruction. The identifiers reference logical resisters that are mapped to corresponding physical registers.
One challenge with such processors is to manage and track the usage of registers. One conventional approach is to define an in-order state for each register. For example, if an instruction has been executed and all other previous instructions have also been executed, the values generated by the instructions are stored as the register's in-order state. The instruction is then considered “retired.”
With the UltraSPARC™ 5, v. 9 architecture for microprocessors, physical integer registers can store two types of data: an integer destination operand and a condition code register. By allowing each physical register to store a copy of the condition codes, out-of-order instruction execution is made more efficient.
There is, however, a major drawback to storing both the integer destination operands and condition codes together in the integer registers. Determining exactly when a physical register becomes “free” (i.e., it is no longer storing useful data and can therefore be reused) becomes significantly more difficult. This increased difficulty arises because a physical register's destination operand may become obsolete or invalid at a different time than its condition code register. Therefore, physical registers can become partly free before they become entirely free. Unless a register is entirely free, however, it is not practical to reuse it to store additional data.
The difficulty associated with determining when a physical register can be reused becomes problematic when enforcing the requirement, as does the UltraSPARC™ 5 microprocessor, that for each physical register that is assigned to an incoming instruction for use as a destination operand, exactly one physical register must be returned to the list of free physical registers.